前面幾個章節有提到Service type LoadBalancer,這個service type在雲端上依賴cloud vendor的loadbalancer得以實作,而在地端想要有同樣的功能體驗則大致上有兩種做法,第一種是透過硬體Loadbalancer串接,且有提供Kubernetes custom controller/CRD之類的廠商(ex. F5 BIG-IP),而另一種則是透過software實作,達成類似情境。
而我們這裡能選擇就只有後者這種方式(沒有前者的機器),過去提到這一塊最著名的莫過於MetalLB,也是我工作上常選擇的。但前陣子因緣際會參與了一場線上的meetup,內容是介紹kubesphere的架構,kubesphere內的NLB選擇為OpenELB(PorterLB),這也讓我心裡想著改天也得來試玩看看。
進行安裝
kubectl apply -f https://raw.githubusercontent.com/kubesphere/porter/master/deploy/porter.yaml
確認porter-system namespace下,有兩個completed、一個running
當節點存在複數網卡時,需定義Annotation的網卡IP。(單一網卡則不用)
kubectl annotate nodes vm01 layer2.porter.kubesphere.io/v1alpha1="192.168.1.231"
kubectl annotate nodes vm02 layer2.porter.kubesphere.io/v1alpha1="192.168.1.232"
kubectl annotate nodes vm03 layer2.porter.kubesphere.io/v1alpha1="192.168.1.233"
kubectl annotate nodes vm04 layer2.porter.kubesphere.io/v1alpha1="192.168.1.234"
kubectl annotate nodes vm05 layer2.porter.kubesphere.io/v1alpha1="192.168.1.235"
佈署layer2的設定,與IP Pools。
kubectl apply -f porter-layer2-eip.yaml
apiVersion: network.kubesphere.io/v1alpha2
kind: Eip
metadata:
name: porter-layer2-eip
spec:
address: 192.168.1.240-192.168.1.250
interface: ens34 ##對應server上網卡
protocol: layer2
快速佈署一個測試用的Nginx
kubectl create ns test
kubectl apply -f test-nginx.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
namespace: test
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
---
kind: Service
apiVersion: v1
metadata:
name: test-nginx-svc
namespace: test
annotations:
lb.kubesphere.io/v1alpha1: porter
protocol.porter.kubesphere.io/v1alpha1: layer2
eip.porter.kubesphere.io/v1alpha2: porter-layer2-eip
spec:
selector:
app: nginx
type: LoadBalancer
ports:
- name: http
port: 80
targetPort: 80
externalTrafficPolicy: Cluster
我們這邊設定的externalTrafficPolicy: Cluster,特性上是不會保留Client IP的。
incomming request會進入任一worker節點,透過cluster(kube-proxy轉發至對應pod)
觀察一下service確認我們拿到了192.168.1.240的ip
打開瀏覽器檢查一下,服務正常
檢查一下log,發現來源IP為10.233系列的,為Cluster內的IP,如預期沒有留存到Client IP。
在筆電上試著PING看看192.168.1.240,會發現是由192.168.1.234(vm04)回應
而我們的nginx則是在192.168.1.235(vm05)上。
再次將service移除、並重新添加並修改規則為externalTrafficPolicy: local
這是能夠保留client IP的方式(實務上我們很多情境皆會要求保留來源IP),因為這個規則不會透過kube-proxy轉發,而是直接流向host pod,也就是說incomming request會流入能夠回應的pod的節點(這裡指的就是nginx所在節點)。
佈署完後一樣是取得192.168.1.240的IP,使用ping呼叫,發現就是由192.168.1.235(vm05進行回傳),與預期一致。
檢查nginx log,確認可以看到log真正的client ip(192.168.1.134)了
明天就可以來用用ingress controller將服務正式hosting起來了。
官網有強調要打開kube-proxy IPVS strict ARP,這個部分倒是與MetalLB一致,但我這次用的是iptables,所以不管好像也沒差。初步看起來的感覺是openELB應該是更lightweight的選擇(雖然我認為MetalLB也是十分輕巧、設定簡單),不過都還用的很少需要再觀察觀察~